package net.whzjkj.gateway.core.manager;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;
import net.whzjkj.gateway.core.handler.AbstractChannelInitializer;
import net.whzjkj.gateway.core.server.AbstractNettyServer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Set;

/**
 * @description:
 * @author: Mr.Hu
 * @create: 2018-10-31 16:39
 **/
@Slf4j
@Component
public class TcpServer extends AbstractNettyServer {
    private ServerBootstrap serverBootstrap;
    @Resource
    private AbstractChannelInitializer<? extends Channel> channelInitializer;

    @Override
    public void setChannelInitializer(ChannelInitializer<? extends Channel> initializer) {
        super.channelInitializer = channelInitializer;
    }

    @Override
    public TransmissionProtocol getTransmissionProtocol() {
        return null;
    }

    @Override
    public void startServer() throws Exception {
        try {
            serverBootstrap = new ServerBootstrap();
            Map<ChannelOption<?>, Object> channelOptions = nettyConfig.getChannelOptions();
            if(null != channelOptions){
                Set<ChannelOption<?>> keySet = channelOptions.keySet();
                // 获取configuration配置到channelOption
                for(ChannelOption option : keySet)
                {
                    serverBootstrap.option(option, channelOptions.get(option));
                }
            }
            // reactor多线程模型，配置bossGroup和workGroup
            // bossGroup和workGroup使用spring容器管理
            serverBootstrap.group(getBossGroup(), getWorkerGroup())
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(channelInitializer);
            // 绑定端口，启动并监听
            Channel serverChannel = serverBootstrap.bind(nettyConfig.getSocketAddress()).sync()
                    .channel();
            ALL_CHANNELS.add(serverChannel);
        } catch(Exception e) {
            log.error("TCP Server start error {}, going to shut down", e);
            super.stopServer();
            throw e;
        }
    }
}
